home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2001 December / pcwk12201b.iso / Wersje pelne i specjalne / Winamp 2.77 i 3.0beta / wasabi-sdk_beta1.exe / studio / common / blending.h < prev    next >
C/C++ Source or Header  |  2001-10-08  |  10KB  |  404 lines

  1. /*
  2.  
  3.   Nullsoft WASABI Source File License
  4.  
  5.   Copyright 1999-2001 Nullsoft, Inc.
  6.  
  7.     This software is provided 'as-is', without any express or implied
  8.     warranty.  In no event will the authors be held liable for any damages
  9.     arising from the use of this software.
  10.  
  11.     Permission is granted to anyone to use this software for any purpose,
  12.     including commercial applications, and to alter it and redistribute it
  13.     freely, subject to the following restrictions:
  14.  
  15.     1. The origin of this software must not be misrepresented; you must not
  16.        claim that you wrote the original software. If you use this software
  17.        in a product, an acknowledgment in the product documentation would be
  18.        appreciated but is not required.
  19.     2. Altered source versions must be plainly marked as such, and must not be
  20.        misrepresented as being the original software.
  21.     3. This notice may not be removed or altered from any source distribution.
  22.  
  23.  
  24.   Brennan Underwood
  25.   brennan@nullsoft.com
  26.  
  27. */
  28.  
  29. #ifndef _BLENDING_H_
  30. #define _BLENDING_H_
  31.  
  32. #include "common.h"
  33.  
  34. class COMEXP Blenders {
  35.   public:
  36.     static void init();
  37.     static unsigned int inline BLEND_ADJ1(unsigned int a, unsigned int b, int alpha); 
  38.     static unsigned int inline BLEND_ADJ2(unsigned int a, unsigned int b); 
  39.     static unsigned int inline BLEND_ADJ3(unsigned int a, unsigned int b, int alpha); 
  40.     static unsigned int inline BLEND_MUL(unsigned int a, int v);
  41.     static unsigned int inline BLEND_AVG(unsigned int a, unsigned int b);
  42.     static unsigned int inline BLEND4(unsigned int *p1, unsigned int w, int xp, int yp);
  43.  
  44.     #ifndef NO_MMX
  45.       static int inline MMX_AVAILABLE() { return mmx_available; }
  46.       static unsigned int inline BLEND_ADJ1_MMX(unsigned int a, unsigned int b, int alpha); 
  47.       static unsigned int inline BLEND_ADJ2_MMX(unsigned int a, unsigned int b); 
  48.       static unsigned int inline BLEND_ADJ3_MMX(unsigned int a, unsigned int b, int alpha); 
  49.       static unsigned int inline BLEND_MUL_MMX(unsigned int a, int v);
  50.       static unsigned int inline BLEND_AVG_MMX(unsigned int a, unsigned int b);
  51.       static unsigned int inline BLEND4_MMX(unsigned int *p1, unsigned int w, int xp, int yp);
  52.       static void inline BLEND_MMX_END() {
  53.         if (mmx_available)  __asm emms; 
  54.       }
  55.     #endif
  56.  
  57.   private:
  58.     static unsigned char alphatable[256][256];
  59.     #ifndef NO_MMX
  60.       static int mmx_available;
  61.     #endif
  62. };
  63.  
  64.  
  65. // NON MMX
  66.  
  67. // average blend of a and b.
  68. unsigned int inline Blenders::BLEND_AVG(unsigned int a, unsigned int b)
  69. {
  70.     return ((a>>1)&~((1<<7)|(1<<15)|(1<<23)))+((b>>1)&~((1<<7)|(1<<15)|(1<<23)));
  71. }
  72.  
  73.  
  74. // multiplies 32 bit color A by scalar V (0-255)
  75. unsigned int inline Blenders::BLEND_MUL(unsigned int a, int v)
  76. {
  77.     register int t;
  78.     t=Blenders::alphatable[a&0xFF][v];
  79.     t|=Blenders::alphatable[(a&0xFF00)>>8][v]<<8;
  80.     t|=Blenders::alphatable[(a&0xFF0000)>>16][v]<<16;
  81.     t|=Blenders::alphatable[(a&0xFF000000)>>24][v]<<24;
  82.     return t;
  83. }
  84.  
  85.  
  86. // V is scalar (0-255), (1.0-V)*b + V*a
  87. unsigned int inline Blenders::BLEND_ADJ1(unsigned int a, unsigned int b, int v)
  88. {
  89.     register int t;
  90.     t=Blenders::alphatable[b&0xFF][0xFF-v]+Blenders::alphatable[a&0xFF][v];
  91.     t|=(Blenders::alphatable[(b&0xFF00)>>8][0xFF-v]+Blenders::alphatable[(a&0xFF00)>>8][v])<<8;
  92.     t|=(Blenders::alphatable[(b&0xFF0000)>>16][0xFF-v]+Blenders::alphatable[(a&0xFF0000)>>16][v])<<16;
  93.     t|=(Blenders::alphatable[(b&0xFF000000)>>24][0xFF-v]+Blenders::alphatable[(a&0xFF000000)>>24][v])<<24;
  94.     return t;
  95. }
  96.  
  97. // returns a*(1.0-Alpha(b)) + b
  98. unsigned int inline Blenders::BLEND_ADJ2(unsigned int a, unsigned int b)
  99. {
  100.     register int t,z;
  101.   int v=0xff-((b>>24)&0xff);
  102.     t=Blenders::alphatable[a&0xFF][v]+(b&0xFF);
  103.   if (t > 0xFF) t=0xff;
  104.   z=(Blenders::alphatable[(a&0xFF00)>>8][v]<<8)+(b&0xFF00);
  105.   if (z > 0xFF00) z=0xff00;
  106.   t|=z;
  107.     z=(Blenders::alphatable[(a&0xFF0000)>>16][v]<<16)+((b&0xFF0000));
  108.   if (z > 0xFF0000) z=0xff0000;
  109.   t|=z;
  110.     z=(Blenders::alphatable[(a&0xFF000000)>>24][v])+((b&0xFF000000)>>24);
  111.   if (z > 0xFF) z=0xff;
  112.     return t|(z<<24);
  113. }
  114.  
  115. // returns a*(1-Alpha(b)*W) + b*W, clamped (W is scalar 0-0xff). 
  116. unsigned int inline Blenders::BLEND_ADJ3(unsigned int a, unsigned int b, int w)
  117. {
  118.     register int t,z;
  119.   int v=0xff-Blenders::alphatable[(b>>24)&0xff][w];
  120.  
  121.     t=Blenders::alphatable[a&0xFF][v]+Blenders::alphatable[b&0xFF][w];
  122.   if (t > 0xFF) t=0xFF;
  123.   z=Blenders::alphatable[(a&0xFF00)>>8][v]+Blenders::alphatable[(b&0xFF00)>>8][w];
  124.   if (z > 0xFF) z=0xFF;
  125.   t|=z<<8;
  126.     z=Blenders::alphatable[(a&0xFF0000)>>16][v]+Blenders::alphatable[(b&0xFF0000)>>16][w];
  127.   if (z > 0xFF) z=0xFF;
  128.   t|=z<<16;
  129.     z=Blenders::alphatable[(a&0xFF000000)>>24][v]+Blenders::alphatable[(b&0xFF000000)>>24][w];
  130.   if (z > 0xFF) z=0xFF;
  131.     return t|(z<<24);
  132. }
  133.  
  134. unsigned int __inline Blenders::BLEND4(unsigned int *p1, unsigned int w, int xp, int yp)
  135. {
  136.   register int t;
  137.   unsigned char a1,a2,a3,a4;
  138.   xp=(xp>>8)&0xff;
  139.   yp=(yp>>8)&0xff;
  140.   a1=alphatable[255-xp][255-yp];
  141.   a2=alphatable[xp][255-yp];
  142.   a3=alphatable[255-xp][yp];
  143.   a4=alphatable[xp][yp];
  144.   t=alphatable[p1[0]&0xff][a1]+alphatable[p1[1]&0xff][a2]+alphatable[p1[w]&0xff][a3]+alphatable[p1[w+1]&0xff][a4];
  145.   t|=(alphatable[(p1[0]>>8)&0xff][a1]+alphatable[(p1[1]>>8)&0xff][a2]+alphatable[(p1[w]>>8)&0xff][a3]+alphatable[(p1[w+1]>>8)&0xff][a4])<<8;
  146.   t|=(alphatable[(p1[0]>>16)&0xff][a1]+alphatable[(p1[1]>>16)&0xff][a2]+alphatable[(p1[w]>>16)&0xff][a3]+alphatable[(p1[w+1]>>16)&0xff][a4])<<16;
  147.   t|=(alphatable[(p1[0]>>24)&0xff][a1]+alphatable[(p1[1]>>24)&0xff][a2]+alphatable[(p1[w]>>24)&0xff][a3]+alphatable[(p1[w+1]>>24)&0xff][a4])<<24;
  148.   return t;      
  149. }
  150.  
  151.  
  152.  
  153.  
  154. #ifndef NO_MMX
  155.  
  156.  
  157. #pragma warning( push, 1 )
  158. #pragma warning(disable: 4799)
  159.  
  160. static unsigned int const Blenders__mmx_revn2[2]={0x01000100,0x01000100};
  161. static unsigned int const Blenders__mmx_zero[2];
  162. static unsigned int const Blenders__mmx_one[2]={1,0};
  163.  
  164. /// MMX
  165.  
  166. // average blend of a and b.
  167. unsigned int inline Blenders::BLEND_AVG_MMX(unsigned int a, unsigned int b)
  168. {
  169.     return ((a>>1)&~((1<<7)|(1<<15)|(1<<23)))+((b>>1)&~((1<<7)|(1<<15)|(1<<23)));
  170. }
  171.  
  172.  
  173. // multiplies 32 bit color A by scalar V (0-255)
  174. unsigned int inline Blenders::BLEND_MUL_MMX(unsigned int a, int v)
  175. {
  176.   __asm
  177.   {
  178.     movd mm3, [v] // VVVVVVVV
  179.     
  180.     movd mm0, [a]
  181.     packuswb mm3, mm3 // 0000HHVV
  182.  
  183.     punpcklbw mm0, [Blenders__mmx_zero]
  184.     punpcklwd mm3, mm3 // HHVVHHVV
  185.         
  186.     punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV
  187.  
  188.     pmullw mm0, mm3      
  189.     
  190.     psrlw mm0, 8
  191.     
  192.     packuswb mm0, mm0
  193.  
  194.     movd eax, mm0
  195.   }
  196. }
  197.  
  198.  
  199. // V is scalar (0-255), (1.0-V)*b + V*a
  200. unsigned int inline Blenders::BLEND_ADJ1_MMX(unsigned int a, unsigned int b, int v)
  201. {
  202.   __asm
  203.   {
  204.     movd mm3, [v] // VVVVVVVV
  205.     
  206.     movd mm0, [a]
  207.     packuswb mm3, mm3 // 0000HHVV
  208.  
  209.     movd mm1, [b]
  210.     paddusw mm3, [Blenders__mmx_one]
  211.         
  212.     movq mm4, [Blenders__mmx_revn2]
  213.     punpcklwd mm3, mm3 // HHVVHHVV
  214.  
  215.     punpcklbw mm0, [Blenders__mmx_zero]
  216.     punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV
  217.  
  218.     punpcklbw mm1, [Blenders__mmx_zero]
  219.     psubw mm4, mm3
  220.  
  221.     pmullw mm0, mm3      
  222.     pmullw mm1, mm4
  223.     
  224.     paddw mm0, mm1
  225.  
  226.     psrlw mm0, 8
  227.     
  228.     packuswb mm0, mm0
  229.  
  230.     movd eax, mm0
  231.   }
  232. }
  233.  
  234. // returns a*(1.0-Alpha(b)) + b
  235. unsigned int inline Blenders::BLEND_ADJ2_MMX(unsigned int a, unsigned int b)
  236. {
  237.   __asm
  238.   {
  239.     movd mm3, [b] // VVVVVVVV
  240.     movq mm4, [Blenders__mmx_revn2]
  241.     
  242.     movd mm0, [a]
  243.     psrld mm3, 24
  244.  
  245.     movd mm1, [b]
  246.     paddusw mm3, [Blenders__mmx_one]
  247.     
  248.     punpcklwd mm3, mm3 // HHVVHHVV
  249.     punpcklbw mm0, [Blenders__mmx_zero]
  250.         
  251.     punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV
  252.     punpcklbw mm1, [Blenders__mmx_zero]
  253.  
  254.     psubw mm4, mm3
  255.  
  256.     pmullw mm0, mm4      
  257.     // stall
  258.  
  259.     // stall
  260.     
  261.     // stall
  262.     
  263.     psrlw mm0, 8
  264.     // stall
  265.  
  266.     paddw mm0, mm1
  267.     // stall
  268.     
  269.     packuswb mm0, mm0
  270.     // stall
  271.  
  272.     movd eax, mm0
  273.   }
  274. }
  275.  
  276. // returns a*(1-Alpha(b)*W) + b*W, clamped (W is scalar 0-0xff). 
  277. unsigned int inline Blenders::BLEND_ADJ3_MMX(unsigned int a, unsigned int b, int w)
  278. {
  279.   __asm
  280.   {
  281.     movd mm3, [b] // VVVVVVVV
  282.     movd mm5, [w]
  283.  
  284.     movd mm0, [a]
  285.     psrld mm3, 24
  286.  
  287.     movd mm1, [b]
  288.     paddusw mm3, [Blenders__mmx_one]
  289.  
  290.     movq mm4, [Blenders__mmx_revn2]
  291.     pmullw mm3, mm5
  292.  
  293.     packuswb mm5, mm5 
  294.     punpcklbw mm0, [Blenders__mmx_zero]
  295.  
  296.     punpcklwd mm5, mm5        
  297.     punpcklbw mm1, [Blenders__mmx_zero]
  298.  
  299.     psrlw mm3, 8
  300.     punpckldq mm5, mm5
  301.         
  302.     paddusw mm3, [Blenders__mmx_one]
  303.  
  304.     punpcklwd mm3, mm3 // HHVVHHVV
  305.  
  306.     punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV
  307.  
  308.  
  309.     psubw mm4, mm3
  310.  
  311.     pmullw mm0, mm4      
  312.     pmullw mm1, mm5
  313.     
  314.     paddusw mm0, mm1
  315.  
  316.     psrlw mm0, 8
  317.     
  318.     packuswb mm0, mm0
  319.  
  320.     movd eax, mm0
  321.   }
  322. }
  323.  
  324. // does bilinear filtering. p1 is upper left pixel, w is width of framebuffer
  325. // xp and yp's low 16 bits are used for the subpixel positioning.
  326. unsigned int inline Blenders::BLEND4_MMX(unsigned int *p1, unsigned int w, int xp, int yp)
  327. {
  328.   __asm
  329.   {
  330.     movd mm6, xp
  331.     mov eax, p1
  332.  
  333.     movd mm7, yp
  334.     mov esi, w
  335.  
  336.     movq mm4, Blenders__mmx_revn2
  337.     psrlw mm6, 8
  338.  
  339.     movq mm5, Blenders__mmx_revn2
  340.     psrlw mm7, 8
  341.  
  342.     movd mm0, [eax]
  343.     punpcklwd mm6,mm6
  344.  
  345.     movd mm1, [eax+4]
  346.     punpcklwd mm7,mm7
  347.  
  348.     movd mm2, [eax+esi*4]
  349.     punpckldq mm6,mm6
  350.  
  351.     movd mm3, [eax+esi*4+4]
  352.     punpckldq mm7,mm7
  353.  
  354.     punpcklbw mm0, [Blenders__mmx_zero]
  355.     psubw mm4, mm6
  356.  
  357.     punpcklbw mm1, [Blenders__mmx_zero]
  358.     pmullw mm0, mm4
  359.  
  360.     punpcklbw mm2, [Blenders__mmx_zero]
  361.     pmullw mm1, mm6
  362.  
  363.     punpcklbw mm3, [Blenders__mmx_zero]
  364.     psubw mm5, mm7
  365.  
  366.     pmullw mm2, mm4
  367.     pmullw mm3, mm6
  368.  
  369.     paddw mm0, mm1
  370.     // stall (mm0)
  371.  
  372.     psrlw mm0, 8
  373.     // stall (waiting for mm3/mm2)
  374.  
  375.     paddw mm2, mm3
  376.     pmullw mm0, mm5
  377.  
  378.     psrlw mm2, 8
  379.     // stall (mm2)
  380.  
  381.     pmullw mm2, mm7
  382.     // stall
  383.  
  384.     // stall (mm2)
  385.  
  386.     paddw mm0, mm2
  387.     // stall
  388.  
  389.     psrlw mm0, 8
  390.     // stall
  391.  
  392.     packuswb mm0, mm0
  393.     // stall
  394.  
  395.     movd eax, mm0
  396.   }
  397. }
  398.  
  399. #pragma warning( pop ) 
  400.  
  401. #endif
  402.  
  403.  
  404. #endif